<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
use think\Request;
use think\facade\Config;//引入配置
use TCPDF;
use Elasticsearch\ClientBuilder;
use \think\facade\Lang;

class Esadmin extends Base
{   

    private $client;
    private $redis;
    private $suoyin='ceshi';
    private $hosts = [
        'elastic:Lily8888@127.0.0.1:9200'  // SSL to IP + Port
    ];

    public function __construct(){
        parent::__construct();
        $this->client=ClientBuilder::create()->setHosts($this->hosts)->setRetries(0)->build();

        $this->redis = new \Redis();
        $this->redis->connect(config('app.redis_ip'), 6379);
        $this->redis->auth(config('app.redis_Secret'));
        $this->redis->select(3);
    }
   
    /*创建型号推荐索引*/
    public function tuijian_part_number_index(){
        $params['index']='tuijian_part_number';
        $params['body']['settings']=[
            'number_of_shards' => 1,
            'analysis' => [
                'filter' => [
                    'autocomplete_filter' => [
                        'type' => 'edge_ngram',
                        'min_gram' => 1,
                        'max_gram' => 20,
                        "pattern" => " ",
                        "replacement" => "",
                   ],
                ],
                'analyzer' => [
                    'autocomplete' => [
                        'type' => 'custom',
                        'tokenizer' => 'keyword',
                        'filter' => ['lowercase', 'autocomplete_filter']
                    ],
                ]   
            ]
        ];
        $data['Part_Number']=['type' => 'text','analyzer' => 'autocomplete','fields'=>['field'=>['type'=>'keyword']]];
        $data['img']=['type' => 'text','analyzer' => 'autocomplete','fields'=>['field'=>['type'=>'keyword']]];
        $data['url']=['type' => 'text','analyzer' => 'autocomplete','fields'=>['field'=>['type'=>'keyword']]];
        $params['body']['mappings']['properties']=$data;
        $this->client->indices()->create($params);
    }

    /*上传型号推荐*/
    public function tuijian_part_number_upload(){
        $redis_zhu=$this->redis->keys("*");
        sort($redis_zhu);
        $i=1;
        foreach ($redis_zhu as $key => $value) {
           $hMget=$this->redis->hMget($value,['Part Number','img','url']);
           $params['body'][] = [
                'index' => [
                    '_index' => 'tuijian_part_number',
                    '_id' => $i,
                ]
            ];
            $data['Part_Number']=$hMget['Part Number'];
            $data['img']=$hMget['img'];
            $data['url']=$hMget['url'];
            $params['body'][] = $data;
            if (count($params['body']) % 1000 == 0) {
                $responses = $this->client->bulk($params);
                $params = ['body' => []];
                unset($responses);
            }
            $i++;
        }
        if (!empty($params['body'])) {
            $responses = $this->client->bulk($params);
        }
    }
    
    /*推荐搜索接口*/
    public function tuijian_part_number_search($Part_Number,$num){
        $recommend = [
            'index' => 'tuijian_part_number',
            'body' => [
                "query" => [
                    "more_like_this" => [
                      "fields" => ["Part_Number"],
                      "like" => $Part_Number,
                      "min_term_freq" => 1,
                      "max_query_terms" => 25,
                    ]
                ],
                "size"=>$num,
                "sort"=>[
                    "_score"=> [
                      "order"=>"desc"
                    ]
                ]
            ]
        ];
        $recommend_result = $this->client->search($recommend);
        $data=$recommend_result['hits']['hits'];
        return $data;
    }

     /*创建索引*/
    public function index(){
        /*创建*/
        $params['index']=$this->suoyin;
        $params['body']['settings']=[
            'number_of_shards' => 1,
            'analysis' => [
                "filter"=>[
                    'shingle' => [
                        'type' => 'shingle'
                    ],
                    'autocomplete_filter' => [
                        'type' => 'edge_ngram',
                        'min_gram' => 1,
                        'max_gram' => 20,
                        "pattern" => " ",
                        "replacement" => "",
                   ],

                ],
                'analyzer' => [
                    'autocomplete' => [
                        'type' => 'custom',
                        'tokenizer' => 'standard',
                        "char_filter"=> [ "html_strip", 
                                'pre_negs' => [
                                'type' => 'pattern_replace',
                                'pattern' => '(\\w+)\\s+((?i:never|no|nothing|nowhere|noone|none|not|havent|hasnt|hadnt|cant|couldnt|shouldnt|wont|wouldnt|dont|doesnt|didnt|isnt|arent|aint))\\b',
                                'replacement' => '~$1 $2'
                            ],
                            'post_negs' => [
                                'type' => 'pattern_replace',
                                'pattern' => '\\b((?i:never|no|nothing|nowhere|noone|none|not|havent|hasnt|hadnt|cant|couldnt|shouldnt|wont|wouldnt|dont|doesnt|didnt|isnt|arent|aint))\\s+(\\w+)',
                                'replacement' => '$1 ~$2'
                            ]
                        ],
                        'filter' => ['lowercase', 'stop', 'kstem','shingle']
                        ,"stopwords"=> [ "and", "the" ,"mm","n","N","lbf","a","MM","-"]/*停用词*/
                    ],
                    'autocomplete_p' => [
                        'type' => 'custom',
                        'tokenizer' => 'keyword',
                        'filter' => ['lowercase', 'autocomplete_filter']
                    ],
                ]   
            ]
        ];
        $all['Part_Number']=['type' => 'text','analyzer' => 'autocomplete','index'=>true];
        $all['Part_Numbers']=['type' => 'keyword','normalizer'=>'lowercase'];//为前缀搜索提供
        $all['Part_arr']=['type' => 'keyword','normalizer'=>'lowercase'];//为前缀搜索提供
        $all['Part']=['type' => 'text','analyzer' => 'autocomplete_p','fields'=>['field'=>['type'=>'keyword']]];//推荐
        $all['Content']=['type' => 'nested'];
        $all['Content_zh']=['type' => 'nested'];
        $all['Tag']=['type' => 'text','index'=>true];
        $all['Tag_zh']=['type' => 'text','index'=>true,'analyzer' => 'ik_max_word'];
        $all['Tag_url']=['type'=>'text','index'=>false];
        $all['Tag_zh_url']=['type'=>'text','index'=>false];
        $all['img']=['type' => 'text','index'=>false];
        $all['url']=['type' => 'text','index'=>false];
        $all['brand_url']=['type' => 'text','index'=>false];
        $all['brand']=['type' => 'text','index'=>false];
        $all['maxclass']=['type' => 'text','index'=>false];
        $params['body']['mappings']['properties']=$all;
        $this->client->indices()->create($params);
    }
    public function replace_fh($str){
        $arr=array(" ","_","(",")",'.');
        $s=$str;
        foreach ($arr as $key => $value) {
            $s=str_replace($value,'',$s);
        }
        return strtolower($s);
    }
    
    public function index_upload(){
        $redis_zhu=$this->redis->keys("*");
        sort($redis_zhu);
        $i=1;
        $dis_fields=array('id','Pid','tablename','tablename','brand_url','brand','detail_field','display_detail','class_id','c_id','Part Number','dimg','img','url','maxclass');
        foreach ($redis_zhu as $key => $value) {
           $hMget=$this->redis->hGetAll($value);
           $params['body'][] = [
                'index' => [
                    '_index' => $this->suoyin,
                    '_id' => $i,
                ]
            ];
            $content=array();
            $content_str='';
            $content_zh=array();
            $content_zh_str='';
            if(isset($hMget['brand'])&&isset($hMget['brand_url'])){
                $data['brand']=$hMget['brand'];
                $data['brand_url']=$hMget['brand_url'];
            }else{
                $data['brand']='';
                $data['brand_url']='';
            }
            $data['Part_Number']=$hMget['Part Number'];
            $data['Part_Numbers']=$hMget['Part Number'];
            $data['Part_arr']=$hMget['Part_arr'];
            $data['Part']=$hMget['Part Number'];
            $data['img']=$hMget['img'];
            $data['url']=$hMget['url'];
            $data['maxclass']=$hMget['maxclass'];
            
            foreach ($hMget as $k => $v) {
                if(!in_array($k,$dis_fields)){
                    if($k!='tag'){
                        $content[$this->replace_fh($k)]=$k." || ".$v;

                        if(lang::has(trim($k))==true){
                            $k_lang=lang(trim($k));
                        }else{
                            $k_lang=trim($k);
                        }
                        if(lang::has(trim($v))==true){
                            $v_lang=lang(trim($v));
                        }else{
                            $v_lang=trim($v);
                        }
                        $content_zh[$this->replace_fh($k_lang)]=$k_lang." || ".$v_lang;
                    }else{
                        if(!empty($hMget['tag'])){
                            $tag=json_decode(base64_decode($hMget['tag']),'true');
                            $tagall=[];
                            $tagall_zh=[];
                            foreach ($tag as $k1 => $v1) {
                                $tagall[]=$k1;
                                if(lang::has(trim($k1))==true){
                                    $k1_lang=lang(trim($k1));
                                }else{
                                    $k1_lang=trim($k1);
                                }
                                $tagall_zh[]=$k1_lang;
                            }
                        }else{
                            $tagall=[];
                        }
                    }
                }
            }

            $data['Content']=$content;
            $data['Content_zh']=$content_zh;
           
            $data['Tag']=$tagall;
            $data['Tag_zh']=$tagall_zh;
            if(empty($hMget['tag'])){
                $data['Tag_url']='';
            }else{
                $data['Tag_url']=$hMget['tag'];
            }
            if(!empty($hMget['tag'])){
                $Tag_zh_url=array();
                $Tag_zh=json_decode(base64_decode($hMget['tag']),'true');

                foreach ($Tag_zh as $tagz => $tag_v) {
                    if(lang::has(trim($tagz))==true){
                        $tag_lang=lang(trim($tagz));
                    }else{
                        $tag_lang=trim($tagz);
                    }
                    $Tag_zh_url[$tag_lang]=$tag_v;
                }

                $Tag_zh_url=base64_encode(json_encode($Tag_zh_url));
                
            }else{
                $Tag_zh_url='';
            }    
            $data['Tag_zh_url']=$Tag_zh_url;
            $params['body'][] = $data;
            if (count($params['body']) % 1000 == 0) {
                $responses = $this->client->bulk($params);
                $params = ['body' => []];
                unset($responses);
            }
            $i++;
        }
        if (!empty($params['body'])) {
            $responses = $this->client->bulk($params);
        }
    }

    /*型号搜索不存在中英文，有四步 精准 包含 前缀 模糊 返回顺序不能错*/
    public function part_number_search($Part_Number){
        /*精准搜索*/
        $jing = [
            'index' => $this->suoyin,
            'body' => [
                "query" => [
                    "constant_score"=>[
                        'filter'=>[
                            "term"=>[
                                'Part_Numbers'=>$Part_Number
                            ],
                        ]
                    ],
                ],
            ]
        ];
        $jing_result = $this->client->search($jing);
        $jing_data=$jing_result['hits']['hits'];
        /*if(!empty($jing_data)){
            Header("Location: ".$jing_data[0]['_source']['url']);
        }*/
        /*包含搜索*/
        $bao = [
            'index' => $this->suoyin,
            'body' => [
                "query" => [
                    "match"=>[
                        'Part_Number'=>[
                            'query'=>$Part_Number,
                            'minimum_should_match'=>"100%"
                        ]
                    ],
                ],
                "track_scores"=>"true",
                "sort"=>[
                    "_score"=> [
                        "order"=>"desc"
                    ]
                ]
            ]
        ];
        $bao_result = $this->client->search($bao);
        $bao_data=$bao_result['hits']['hits'];
        /*前缀搜索*/
        $jin = [
            'index' => $this->suoyin,
            'body' => [
                "query" => [
                    "prefix"=>[
                        'Part_Numbers'=>$Part_Number
                    ],
                ],
            ]
        ];
        $jin_result = $this->client->search($jin);
        $jin_data=$jin_result['hits']['hits'];
        /* dump($jin_data);
        exit;*/

        $jin2 = [
            'index' => $this->suoyin,
            'body' => [
                "query" => [
                    "prefix"=>[
                        'Part_arr'=>preg_replace('/[^0-9a-zA-Z]+/i','',$Part_Number)
                    ],
                ],
            ]
        ];
        $jin_result2 = $this->client->search($jin2);
        $jin_data2=$jin_result2['hits']['hits'];
       /* dump(preg_replace('/[^0-9a-zA-Z]+/i',' ',$Part_Number));
        exit;*/
        
        /*模糊搜索*/
        $mo = [
            'index' => $this->suoyin,
            'body' => [
                "query" => [
                    "match"=>[
                        'Part_Number'=>[
                            "query"=>$Part_Number,
                            'fuzziness'=>'AUTO',
                            "minimum_should_match"=>"88%",
                        ]
                    ],
                ],
                "sort"=>[
                    "_score"=> [
                        "order"=>"desc"
                    ]
                ]
            ]
        ];
        $mo = $this->client->search($mo);
        $mo_data=$mo['hits']['hits'];

        $data['bao_data']=$bao_data;
        $data['jin_data']=$jin_data;
        $data['jin_data2']=$jin_data2;
        $data['mo_data']=$mo_data;
        return $data;
    }
    public function class_search($Part_Number){
        /*分类搜索*/
        $default_lang=config('app.default_lang');
        if($default_lang=='en-us'){
           $tagname='Tag';
        }else{
           $tagname='Tag_zh';
        }
        $class = [
            'index' => $this->suoyin,
            'body' => [
                "query" => [
                    "match"=>[
                        $tagname=>[
                            'query'=>$Part_Number,
                            'minimum_should_match'=>"100%"
                        ]
                    ],
                ],
                "track_scores"=>"true",
                "size"=>20,
                "from"=>0,
                "sort"=>[
                    "_score"=> [
                        "order"=>"desc"
                    ]
                ]
            ]
        ];
        $class = $this->client->search($class);
        $class_data=$class['hits']['hits'];
        $data['class_data']=$class_data;
        return $data;
    }
    /*分类和维度搜索 返回顺序不能错*/
    public function weidu_search($Part_Number){
        $default_lang=config('app.default_lang');
        if($default_lang=='en-us'){
           $Contentname='Content';
        }else{
           $Contentname='Content_zh';
        }

        /*字符串处理*/
        $Part_Number=str_replace('x',' ',strtolower($Part_Number));//转小写

        $mo1 = [
            'index' => $this->suoyin,
            'body' => [
                "query" => [
                    'nested'=>[
                        "path"=>$Contentname,
                        "query"=>[
                            "multi_match"=>[
                                "query"=>$Part_Number,
                                "type"=>'best_fields',
                                "tie_breaker"=>0.8,
                                "minimum_should_match"=>"100%",
                                
                            ],
                        ]
                    ] 
                ],
                "track_scores"=>"true",
                "size"=>100,
                "from"=>0,
                "sort"=>[
                    "_score"=> [
                        "order"=>"desc"
                    ]
                ]
            ]
        ];
        $mo1 = $this->client->search($mo1);
        $mo_data1=$mo1['hits']['hits'];

        $mo2 = [
            'index' => $this->suoyin,
            'body' => [
                "query" => [
                    'nested'=>[
                        "path"=>$Contentname,
                        "query"=>[
                            "multi_match"=>[
                                "query"=>$Part_Number,
                                "type"=>'cross_fields',
                                "tie_breaker"=>0.8,
                                "minimum_should_match"=>"100%",
                                
                            ],
                        ]
                    ] 
                ],
                "track_scores"=>"true",
                "size"=>100,
                "from"=>0,
                "sort"=>[
                    "_score"=> [
                        "order"=>"desc"
                    ]
                ]
            ]
        ];

        $mo2 = $this->client->search($mo2);
        $mo_data2=$mo2['hits']['hits'];

        $mo3 = [
            'index' => $this->suoyin,
            'body' => [
                "query" => [
                    'nested'=>[
                        "path"=>$Contentname,
                        "query"=>[
                            "multi_match"=>[
                                "query"=>$Part_Number,
                                "type"=>'cross_fields',
                                "tie_breaker"=>0.8,
                                "minimum_should_match"=>"66%",
                                
                            ],
                        ]
                    ] 
                ],
                "track_scores"=>"true",
                "size"=>100,
                "from"=>0,
                "sort"=>[
                    "_score"=> [
                        "order"=>"desc"
                    ]
                ]
            ]
        ];

        $mo3 = $this->client->search($mo3);
        $mo_data3=$mo3['hits']['hits'];
       
        /*if(!empty($mo_data2)){
           $data['content_data2']=$mo_data2;
        }else{
            if(!empty($mo_data3)){
                $data['content_data2']=$mo_data3;
            }else{
                $d=array();
                $data['content_data2']=$d;
            }
        }*/

        $data['content_data']=$mo_data1;
        $data['content_data2']=$mo_data2;
        $data['content_data3']=$mo_data3;
        
        return $data;
    }
    /*该方法是及其无奈的搜索结果，仅仅用于对型号搜索做处理，极度模糊，为了不影响前面相对精确的搜索单列出来*/
    public function no_way_search($Part_Number){
        $bao = [
            'index' => $this->suoyin,
            'body' => [
                "query" => [
                    "match"=>[
                        'Part_Number'=>[
                            'query'=>$Part_Number,
                            'minimum_should_match'=>"33%"
                        ]
                    ],
                ],
                "track_scores"=>"true",
                "sort"=>[
                    "_score"=> [
                        "order"=>"desc"
                    ]
                ]
            ]
        ];
        $bao_result = $this->client->search($bao);
        $bao_data=$bao_result['hits']['hits'];

        /*最无奈的用推荐*/
        $recommend = [
            'index' => $this->suoyin,
            'body' => [
                "query" => [
                    "more_like_this" => [
                      "fields" => ["Part"],
                      "like" => $Part_Number,
                      "min_term_freq" => 1,
                      "max_query_terms" => 25,
                    ]
                ],
                "size"=>15,
                "sort"=>[
                    "_score"=> [
                      "order"=>"desc"
                    ]
                ]
            ]
        ];

        $recommend_result = $this->client->search($recommend);
        $recommend_data=$recommend_result['hits']['hits'];
        if(empty($recommend_data)){
            $recommend = [
                'index' => $this->suoyin,
                'body' => [
                    "query" => [
                        "more_like_this" => [
                          "fields" => ["Part"],
                          "like" => preg_replace('/[^0-9a-zA-Z]+/i','',$Part_Number),
                          "min_term_freq" => 1,
                          "max_query_terms" => 25,
                        ]
                    ],
                    "size"=>15,
                    "sort"=>[
                        "_score"=> [
                          "order"=>"desc"
                        ]
                    ]
                ]
            ];

            $recommend_result = $this->client->search($recommend);
            $recommend_data=$recommend_result['hits']['hits'];
        }
        $data['bao_data']=$bao_data;
        $data['recommend_data']=$recommend_data;
        //dump($data);exit;
        return $data;

    } 

    public function most_fields($Part_Number){
        $default_lang=config('app.default_lang');
        if($default_lang=='en-us'){
           $Contentname='Content';
        }else{
           $Contentname='Content_zh';
        }

        /*字符串处理*/
        $Part_Number=str_replace('x',' ',strtolower($Part_Number));//转小写
         $mo3 = [
            'index' => $this->suoyin,
            'body' => [
                "query" => [
                    'nested'=>[
                        "path"=>$Contentname,
                        "query"=>[
                            "multi_match"=>[
                                "query"=>$Part_Number,
                                "type"=>'most_fields',
                                "tie_breaker"=>1,
                                "minimum_should_match"=>"66%",
                                
                            ],
                        ]
                    ] 
                ],
                "track_scores"=>"true",
                "size"=>100,
                "from"=>0,
                "sort"=>[
                    "_score"=> [
                        "order"=>"desc"
                    ]
                ]
            ]
        ];

        $mo3 = $this->client->search($mo3);
        $mo_data3=$mo3['hits']['hits'];
        $data['content_data3']=$mo_data3;
        return $data;
    }

    public function qianzhui($Part_Number,$num){

        $default_lang=config('app.default_lang');
        if($default_lang=='en-us'){
           $Contentname='Content';
           $tagname='Tag';
        }else{
           $Contentname='Content_zh';
           $tagname='Tag_zh';
        }

        /*前缀搜索*/
        $jin = [
            'index' => $this->suoyin,
            'body' => [
                "query" => [
                    "prefix"=>[
                        'Part_Numbers'=>$Part_Number
                    ],
                ],
                "size"=>$num,
                "from"=>0,
            ]
        ];
        $jin_result = $this->client->search($jin);
        $jin_data=$jin_result['hits']['hits'];

        
        $class = [
            'index' => $this->suoyin,
            'body' => [
                "query" => [
                    "match_phrase_prefix"=>[
                        $tagname=>[
                            'query'=>$Part_Number,
                            "max_expansions"=> 50
                        ]
                    ],
                ],
                "size"=>$num,
                "from"=>0,
            ]
        ];
        $class_result = $this->client->search($class);
        $class=$class_result['hits']['hits'];


        $Part_Number=str_replace('x',' ',strtolower($Part_Number));//转小写

        $mo1 = [
            'index' => $this->suoyin,
            'body' => [
                "query" => [
                    'nested'=>[
                        "path"=>$Contentname,
                        "query"=>[
                            "multi_match"=>[
                                "query"=>$Part_Number,
                                "type"=>'best_fields',
                                "tie_breaker"=>0.8,
                                "minimum_should_match"=>"100%",
                                
                            ],
                        ]
                    ] 
                ],
                "track_scores"=>"true",
                "size"=>10,
                "from"=>0,
                "sort"=>[
                    "_score"=> [
                        "order"=>"desc"
                    ]
                ]
            ]
        ];
        $mo1 = $this->client->search($mo1);
        $weidu=$mo1['hits']['hits'];

        
       

        $data['jin_data']=$jin_data;
        $data['class']=$class;
       
        $data['weidu']=$weidu;
        return $data;
    }

    public function qianzhui1($Part_Number){
        /*前缀搜索*/
        $jin = [
            'index' => $this->suoyin,
            'body' => [
                "query" => [
                    "prefix"=>[
                        'Part_Numbers'=>$Part_Number
                    ],
                ],
                "size"=>5,
                "from"=>0,
            ]
        ];
        $jin_result = $this->client->search($jin);
        $jin_data=$jin_result['hits']['hits'];

        $data['jin_data']=$jin_data;
        return $data;
    }

    public function check_not_call(){
        $product=Db::table('product_middle_table')->field('Product_Number')->where([['version','=',1]])->select();
        foreach ($product as $key => $value) {
            $data=$this->tuijian_part_number_search($value['Product_Number'],'5');
            foreach ($data as $k => $v) {
                $es=Db::table('es')->where('p','=',$v['_source']['Part_Number'])->find();
                if(empty($es)){
                    $datai = ['p' => $v['_source']['Part_Number']];
                    Db::table('es')->data($datai)->insert();
                }
            }
        }
    }
}